// Copyright (C) joyinter
// All rights reserved.
// 
// Author : Jiang Li
// Date   : 2004-6-4

#ifndef __NETMSG_H_NETMSG__
#define __NETMSG_H_NETMSG__

#include <windows.h>
#include "md5.h"

namespace JoyMessage
{

//##ModelId=44C4B5FC0040
enum UserSexType
{
	//##ModelId=44C4B5FC004F
    US_None,
	//##ModelId=44C4B5FC005D
    US_Male,
	//##ModelId=44C4B5FC005E
    US_Female,
};

//##ModelId=44C4B5FC006D
enum UserStatus
{
	//##ModelId=44C4B5FC007E
    USta_Play,
	//##ModelId=44C4B5FC008C
    USta_Chat,
};

//##ModelId=44C4B5FC00BB
enum ErrorType
{
	//##ModelId=44C4B5FC00BD
    Error_Ok,
	//##ModelId=44C4B5FC00CB
    Error_Failed,
	//##ModelId=44C4B5FC00DA
    Error_AlreadyOnline,
	//##ModelId=44C4B5FC00DB
    Error_NotLogin,
	//##ModelId=44C4B5FC00EA
    Error_NamePass,
	//##ModelId=44C4B5FC00EB
    Error_BadData,
	//##ModelId=44C4B5FC00FA
    Error_Banned,
	//##ModelId=44C4B5FC00FB
    Error_UserMax,
	//##ModelId=44C4B5FC0109
    Error_BadVersion,
	//##ModelId=44C4B5FC010A
    Error_Kicked,
	//##ModelId=44C4B5FC0119
    Error_LevelLow,
	//##ModelId=44C4B5FC011A
    Error_CreditLow,
	//##ModelId=44C4B5FC0128
    Error_LevelHigh,
	//##ModelId=44C4B5FC0138
    Error_RoomClosed,
	//##ModelId=44C4B5FC0139
    Error_ServerDown,
};

#pragma pack(push, 1)


#define DG_MAX_SIZE     0x100000

struct MessageBase;

//##ModelId=44C4B5FC0148
struct DataGram
{
	//##ModelId=44C4B5FC0158
    DWORD   m_size;
	//##ModelId=44C4B5FC0167
    bool    m_crypt;

	//##ModelId=44C4B5FC0168
    MessageBase* GetMessage()
    {
        return (MessageBase*)(this+1);
    }
};

//##ModelId=44C4B5FC0177
enum MessageType
{
	//##ModelId=44C4B5FC0187
    MCT_Min,
#   define JOY_MSG_CLIENT_DEF(type) MCT_##type,
#   include "mc_def.h"
	//##ModelId=44C4B5FC0188
    MCT_Max,

	//##ModelId=44C4B5FC0196
    MST_Min = 2000,
#   define JOY_MSG_SERVER_DEF(type) MST_##type,
#   include "ms_def.h"
	//##ModelId=44C4B5FC0197
    MST_Max,
};

//##ModelId=44C4B5FC01B5
struct MessageHeader
{
	//##ModelId=44C4B5FC01B7
    DWORD   m_size;
	//##ModelId=44C4B5FC01C5
    bool    m_crypto;
	//##ModelId=44C4B5FC01C6
    bool    m_reserved;
};

//##ModelId=44C4B5FC01D4
struct MessageBase : public MessageHeader
{
	//##ModelId=44C4B5FC01E5
    WORD    m_type;
};

//##ModelId=44C4B5FC01F4
template<int _TypeId, typename _SelfType>
struct MessageRoot : public MessageBase
{
public:
    enum
    {
        TypeId = _TypeId,
    };

	//##ModelId=44C4B5FC0213
    typedef MessageRoot<_TypeId, _SelfType> BaseType;
	//##ModelId=44C4B5FC0215
    typedef _SelfType SelfType;

	//##ModelId=44C4B5FC0205
    MessageRoot()
    {
        m_type      = TypeId;
        m_size      = sizeof(SelfType);
        m_crypto    = true;
        m_reserved  = true;
    }

	//##ModelId=44C4B5FC0206
    bool IsValid() const
    {
        if(m_size < sizeof(SelfType) || m_type != TypeId)
        {
            return false;
        }
        return true;
    }
};

#define JOY_MC_TEMPLATE(name) \
    template<int _TypeId, typename _SelfType>\
    struct MC_##name : public MessageRoot<_TypeId, _SelfType>

#define JOY_MC_STRUCT_T(name, baseClass) struct MC_##name : public MC_##baseClass<MCT_##name, MC_##name>


#define JOY_MC_STRUCT(name) struct MC_##name : public MessageRoot<MCT_##name, MC_##name>
#define JOY_MS_STRUCT(name) struct MS_##name : public MessageRoot<MST_##name, MS_##name>

enum
{
    UserName_Max = 31,
    PassWord_Max = 32,
    Nickname_Max = 31,
    UserChat_Max = 260,
    UserTitle_Max = 31,
};

// messages from client.

JOY_MC_TEMPLATE(LoginT)
{

    CHAR    m_username[UserName_Max+1];
    CHAR    m_password[PassWord_Max+1];
    UINT    m_mainVer;  // version of joy_main
    UINT    m_fileVer;  // version of all files of client.

    MC_LoginT()
    {
        memset(m_username, 0, sizeof(m_username));
        memset(m_password, 0, sizeof(m_password));

        m_mainVer = 0;
        m_fileVer = 0;
    }

    void SetUserPass(PCSTR usr, PCSTR pwd)
    {
        lstrcpy(m_username, usr);

        CJoyMD5 hashAlg;    // hash algorithm can be changed here.

        hashAlg.Update(pwd, lstrlen(pwd));
        UINT hashSize = hashAlg.GetHashSize();
        const BYTE* hashValue = hashAlg.GetHashValue();

        for(UINT i = 0; i < hashSize; i ++)
        {
            wsprintf(m_password+i*2, "%.2X", hashValue[i]);
        }
    }

    bool IsValid() const
    {
        if(!BaseType::IsValid())
        {
            return false;
        }

        if(m_username[UserName_Max]!=0 || m_password[PassWord_Max]!=0)
        {
            return false;
        }

        return true;
    }
};

JOY_MC_STRUCT_T(Login, LoginT)
{
};
//added by deng,0304  
//##ModelId=44C4B5FC0232
struct UDPAddrInfo
{
	//##ModelId=44C4B5FC0243
	DWORD  dwType;
	//##ModelId=44C4B5FC0251
	short   n_VIP;
	//##ModelId=44C4B5FC0261
	DWORD  dwLocalIP;
	//##ModelId=44C4B5FC0262
	WORD   wUDPPort;
	//##ModelId=44C4B5FC0271
	DWORD  dwMappingIP;
	//##ModelId=44C4B5FC0272
	WORD  wUDPMappingPort;
	//##ModelId=44C4B5FC0273
	char   sa_netnum[4];
	//##ModelId=44C4B5FC0280
	char   sa_nodenum[6];
	//##ModelId=44C4B5FC0281
	short  cmd;
	//##ModelId=44C4B5FC0291
	u_short reserve;
};

JOY_MC_STRUCT_T(MainLogin, LoginT)
{
    UINT    m_userId;
    UINT    m_roomId;
    int     m_network;
	UDPAddrInfo m_addrinfo;
};

JOY_MC_STRUCT(Logout)
{
};

JOY_MC_STRUCT(ListRoom)
{
    UINT    m_lobbyId;
    UINT    m_regionId;
};

JOY_MC_STRUCT(ListRegion)
{
    UINT    m_lobbyId;
};

JOY_MC_STRUCT(UserStatus)
{
    UserStatus  m_status;
};

JOY_MC_STRUCT(Chat)
{
    UINT    m_dstUser;
    bool    m_private;
    char    m_text[1];

    bool IsValid() const;

    int GetTextLength() const
    {
        return m_size-sizeof(MC_Chat);
    }
    static MC_Chat* Alloc(UINT dstUser, bool priv, PCSTR pszText, int s);
};

JOY_MC_STRUCT(PingRequest)
{
    int m_IP;
    int m_id;
};

JOY_MC_STRUCT(PingResponse)
{
    int m_IP;
    int m_id;
};

#define JOY_MSG_DEF_TRANSMIT(pre, name) \
pre##name()\
{\
    m_crypto = false;\
}\
void SetDataLength(int len)\
{\
    m_size = sizeof(pre##name)-sizeof(char)+len;\
}\
int GetDataLength() const\
{\
    return m_size - sizeof(pre##name)+sizeof(char);\
}

#define JOY_MSG_DEF_CONSTRUCTOR(pre, name) \
pre##name()\
{\
    m_crypto = false;\
}\


JOY_MC_STRUCT(SockTransmitTCP)
{
    JOY_MSG_DEF_TRANSMIT(MC_, SockTransmitTCP)

    INT     m_dstId;
    INT     m_dstIP;
    char    m_data[1];

};

JOY_MC_STRUCT(SockTransmitUDP)
{
    JOY_MSG_DEF_TRANSMIT(MC_, SockTransmitUDP)
    INT     m_srcPort;
    INT     m_dstIP;
    INT     m_dstPort;
    char    m_data[1];
};

JOY_MC_STRUCT(SockAccept)
{
    JOY_MSG_DEF_CONSTRUCTOR(MC_, SockAccept);
    INT     m_srcId;
    INT     m_dstId;
    INT     m_dstIP;
    bool    m_accept;
};

JOY_MC_STRUCT(SockConnect)
{
    JOY_MSG_DEF_CONSTRUCTOR(MC_, SockConnect);
    INT     m_srcId;
    INT     m_dstIP;
    INT     m_dstPort;
};

JOY_MC_STRUCT(SockClose)
{
    JOY_MSG_DEF_CONSTRUCTOR(MC_, SockClose);
    INT     m_dstId;
    INT     m_dstIP;
};

// added by lr 2005-04-29
enum
{
	CS_GAMENAME_MAX = 31,
	CS_MAPNAME_MAX = 31,
	CS_TRENCHNAME_MAX = 31,
};

// added by lr 2005-04-29
//##ModelId=44C4B5FC029F
class CSPlayerInfo
{
public:
	//##ModelId=44C4B5FC02AF
	UINT	m_playid;
	//##ModelId=44C4B5FC02B0
	UINT	m_playRole;
	//##ModelId=44C4B5FC02B1
	UINT	m_userId;
	//##ModelId=44C4B5FC02BF
	char	m_username[UserName_Max+1];
	//##ModelId=44C4B5FC02C0
	char	m_playercsname[UserName_Max + 1];
	//##ModelId=44C4B5FC02C1
	UINT	m_killcount;
	//##ModelId=44C4B5FC02CE
	UINT	m_bekillcount;
	//##ModelId=44C4B5FC02CF
	LONG	m_playtime;
};

// added by lr 2005-04-29
JOY_MC_STRUCT(CSTrench)
{
	enum MC_CSTrench_T 
	{
		TRH_Create		= 1,
		TRH_Connect		= 2,
		TRH_JoinRole	= 3,
		TRH_DisConn		= 4,
		TRH_RoundEnd	= 5,
		TRH_ChangeMap	= 6,
		TRH_MapOver		= 7,

	}		m_trench_type;
	UINT	m_srcUser;
	UINT	m_svrPort;
	UINT	m_roomId;
	UINT	m_trenchId;
	char	m_trenchname[CS_TRENCHNAME_MAX + 1];

	char	m_gamename[CS_GAMENAME_MAX + 1];
	char	m_csmapname[CS_MAPNAME_MAX + 1];
	UINT	m_playingcount;
	UINT	m_maxplayercount;
	UINT	m_spectatorcount;

	CSPlayerInfo	m_players[1];
};


// messages from server

JOY_MS_STRUCT(LoginAccept)
{
    DWORD   m_userId;
    DWORD   m_onlineCount;
};

//##ModelId=44C4B5FC02EE
class UserInfo
{
public:
	//##ModelId=44C4B5FC02FD
	UINT m_userId;
	//##ModelId=44C4B5FC02FE
	char m_nickname[Nickname_Max+1];
	//##ModelId=44C4B5FC02FF
    char m_title[UserTitle_Max+1];
	//##ModelId=44C4B5FC030D
	int  m_level;
	//##ModelId=44C4B5FC030E
    int  m_ladder;
	//##ModelId=44C4B5FC030F
	int  m_winTimes;
	//##ModelId=44C4B5FC0310
	int  m_lossTimes;
	//##ModelId=44C4B5FC031C
	int  m_score;
	//##ModelId=44C4B5FC031D
    int  m_credit;
	//##ModelId=44C4B5FC031E
    int  m_network;
	//##ModelId=44C4B5FC032D
	UserSexType m_sex;
	//##ModelId=44C4B5FC0332
	UserStatus  m_status;
	//##ModelId=44C4B5FC033C
    INT    m_VIP;
};

JOY_MS_STRUCT(EnterRoom)
{
    UserInfo    m_user;
};

JOY_MS_STRUCT(LeaveRoom)
{
    UINT    m_userId;
};

JOY_MS_STRUCT(MainAccept)
{
    // room informations.
    UINT    m_roomId;
    UINT    m_roomPort;
    UINT    m_userIP;
    CHAR    m_noteUrl[128];
    UINT    m_userCount;
    UserInfo    m_users[1];
};

JOY_MS_STRUCT(Error)
{
    ErrorType   m_error;
};

JOY_MS_STRUCT(OnlineCount)
{
    UINT    m_onlineCount;
};

JOY_MS_STRUCT(RegionList)
{
    enum
    {
        REGION_NAME_MAX = 39,
    };
    struct RegionInfo
    {
        char    m_name[REGION_NAME_MAX+1];
        UINT    m_id;
    };
    UINT    m_lobbyId;
    UINT    m_regionCount;
    RegionInfo    m_regions[1];

    bool IsValid() const;
};

JOY_MS_STRUCT(RoomList)
{
    enum
    {
        ROOM_NAME_MAX = 64,
        ROOM_IP_MAX = 16,
    };
    struct RoomInfo
    {
        char    m_name[ROOM_NAME_MAX+1];
        char    m_ip[ROOM_IP_MAX+1];
        UINT    m_port;
        UINT    m_id;
        UINT    m_level;
        UINT    m_levelMax;
        UINT    m_userNow;
        UINT    m_userMax;
        UINT    m_gameId;
        UINT    m_prize;
        UINT    m_credit;
        bool    m_recordScore;

        bool IsTroop() const
        {
            return m_ip[0] == 0;
        }
    };
    UINT    m_lobbyId;
    UINT    m_regionId;
    UINT    m_roomCount;
    RoomInfo    m_rooms[1];
};

JOY_MS_STRUCT(Chat)
{
	UINT m_srcUser;
    UINT m_dstUser;
	bool m_private;    
	char m_text[1];

    bool IsValid() const;

    int GetTextLength() const
    {
        return m_size-sizeof(MS_Chat);
    }
    static MS_Chat* Alloc(UINT srcUser, UINT dstUser, bool priv, PCSTR pszText, int s);
};

JOY_MS_STRUCT(PingRequest)
{
    int m_IP;
    int m_id;
};

JOY_MS_STRUCT(PingResponse)
{
    int m_IP;
    int m_id;
};

JOY_MS_STRUCT(SockTransmitTCP)
{
    JOY_MSG_DEF_TRANSMIT(MS_, SockTransmitTCP)
    INT     m_dstId;
    char    m_data[1];
};

JOY_MS_STRUCT(SockTransmitUDP)
{
    JOY_MSG_DEF_TRANSMIT(MS_, SockTransmitUDP)
    INT     m_srcIP;
    INT     m_srcPort;
    INT     m_dstPort;
    char    m_data[1];
};

JOY_MS_STRUCT(SockAccept)
{
    JOY_MSG_DEF_CONSTRUCTOR(MS_, SockAccept);
    INT     m_srcId;
    INT     m_dstId;
    bool    m_accept;
};

JOY_MS_STRUCT(SockConnect)
{
    JOY_MSG_DEF_CONSTRUCTOR(MS_, SockConnect);
    UINT    m_dstPort;
    INT     m_srcId;
    INT     m_srcIP;
};

JOY_MS_STRUCT(SockClose)
{
    JOY_MSG_DEF_CONSTRUCTOR(MS_, SockClose);
    INT     m_dstId;
};

// added by lr 2005-04-29
#define CS_TRENCH_SORT_NUMBER	4

// added by lr 2005-04-29
JOY_MS_STRUCT(CSTrench)
{
	struct TrenchSort
	{
		char	m_username[UserName_Max + 1];
		UINT	m_killcount;
		UINT	m_bekillcount;
	};

	enum MS_CSTrench_T 
	{
		TRH_Normal		= 1,
		TRH_PlayersFull	= 2,
		TRH_MapOver		= 3,
	}		m_trench_type;
	UINT	m_srcUser;
	UINT	m_svrPort;
	UINT	m_roomId;
	UINT	m_trenchId;
	char	m_trenchname[CS_TRENCHNAME_MAX + 1];

	char	m_gamename[CS_GAMENAME_MAX + 1];
	char	m_csmapname[CS_MAPNAME_MAX + 1];
	UINT	m_playingcount;
	UINT	m_maxplayercount;
	UINT	m_spectatorcount;
	UINT	m_sortcount;

	TrenchSort		m_sorts[CS_TRENCH_SORT_NUMBER];
	CSPlayerInfo	m_players[1];	
};

#pragma pack(pop)
} // namespace JoyMessage

#endif  // __NETMSG_H_NETMSG__
